/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using System.Xml;
using EvaluationException = System.Qizx.Api.EvaluationException;
using XMLPushStreamBase = System.Qizx.Xdm.XMLPushStreamBase;
using EmptyException = System.Qizx.XQuery.Impl.EmptyException;
using Expression = System.Qizx.XQuery.Op.Expression;
using System.Qizx.Api;
using System.Qizx.XQuery.Op;

namespace System.Qizx.XQuery {

    /// <summary>
    /// A compiled main Query.
    /// This is essentially a module plus a main expression.
    /// </summary>
    public class MainQuery : ModuleContext {
        virtual public XQType Type {
            get {
                return body.getType();
            }

        }
        internal Expression body;
        private IXmlNamespaceResolver _resolver;

        public MainQuery(BasicStaticContext env)
            : this(env, null) {
        }

        public MainQuery(BasicStaticContext env, IXmlNamespaceResolver resolver)
            : base(env) {
            moduleNS = LOCAL_NS;
            _resolver = resolver;
        }

        public override string ConvertPrefixToNamespace(string prefix) {
            if (_resolver != null && prefix != null) {
                string uri = _resolver.LookupNamespace(prefix);
                if (uri != null) return uri;
            }
            return base.ConvertPrefixToNamespace(prefix);
        }

        public virtual void Dump(ExprDisplay d) {
            d.header("MainQuery");
            for (int i = 0; i < declarations.Count; i++) {
                d.child((Expression)declarations[i]);
            }
            d.child("body", body);
            d.end();
        }

        public override void StaticCheck(ModuleManager mman) {
            resetLocals(); // needed for joins
            base.StaticCheck(mman); // module
            // save as locals can be used in globals inits:
            int saveMaxLocalSize = maxLocalSize;
            resetLocals(); // twice is better
            if (body != null) {
                body = simpleStaticCheck(body, 0);
                allocateLocalAddress(lastLocal);
                // dumpLocals2("locals after allocation");
            }
            if (saveMaxLocalSize > maxLocalSize)
                maxLocalSize = saveMaxLocalSize;
        }

        public virtual XQValue Eval(Focus focus, EvalContext context) {
            try {
                return body == null ? System.Qizx.XQuery.XQValues.Empty : body.eval(focus, context);
            } catch (EmptyException e) {
                return System.Qizx.XQuery.XQValues.Empty;
            }
        }

        public virtual void EvalAsEvents(XMLPushStreamBase output, Focus focus, EvalContext context) {
            try {
                body.EvalAsEvents(output, focus, context);
            } catch (EmptyException e) {
            }
        }

        #region extension by CoShare
        public override string PrefixedName(System.Qizx.Api.QName name) {
            if (_resolver != null) {
                string uri = name.Namespace;
                if (uri.Length == 0)
                    return name.Name;
                string prefix = _resolver.LookupPrefix(uri);
                return string.IsNullOrEmpty(prefix) ? (prefix + ":" + name.Name) : name.ToString(); // fallback
            }
            return base.PrefixedName(name);
        }

        public override System.Qizx.XQuery.Op.GlobalVariable lookforGlobalVariable(QName name) {
            GlobalVariable globalVariable = base.lookforGlobalVariable(name);
            if (globalVariable != null)
                return globalVariable;
            IVariableScope scope = _resolver as IVariableScope;
            if (scope != null) {
                GlobalVariable gv = scope.LookupVariable(name);
                if (gv != null) {
                    return this.DeclareGlobal(name, gv.declaredType); //Must return the GlobleVariable in the map;
                }
            }
            return null;
        }

        public override string BaseURI {
            get {
                IVariableScope scope = _resolver as IVariableScope;
                if (scope != null) {
                    string baseURI = scope.BaseURI;
                    if (!string.IsNullOrEmpty(baseURI)) {
                        return baseURI;
                    }
                }
                return base.BaseURI;
            }
            set {
                base.BaseURI = value;
            }
        }
        #endregion

    }
}